import functools
from datetime import datetime

from app.common.log_utils import logger
from app.common.utils import to_security
from app.macro import OrderStatus, TradeCode


def retry(times):
    def wrapper(func):
        @functools.wraps(func)
        def execute(self, action, *args, **kwargs):
            ret = func(self, action, *args, **kwargs)
            if ret is not None:
                return ret

            for i in range(times):
                logger.info(f'trigger {self.account.account} {action} retry')
                ret = func(self, action, *args, **kwargs)
                if ret is not None:
                    return ret

        return execute

    return wrapper


def parse_buy_or_sell(data):
    ret = {
        'success': data['success'],
        'error': data['error'],
    }
    if data['success']:
        ret['hth'] = data['data'][0]['委托编号']
    return ret


def parse_cancel(data):
    return {
        'success': data['success'],
        'error': data['error'],
    }


def parse_query_shares(account, data):
    def _parse(d):
        return {
            'account': account,
            'security': to_security(d['证券代码'], d['交易所代码']),
            'name': d['证券名称'],
            'date': datetime.now().strftime('%Y-%m-%d'),
            'total': int(d['证券数量']),
            'sellable': int(d['可卖数量']),
            'avg_price': float(d['成本价']),
            'market_value': float(d['最新市值'])
        }

    return [_parse(e) for e in data['data']]


mapping = {
    '未报': OrderStatus.CREATED,
    '已报': OrderStatus.CREATED,
    '已撤': OrderStatus.CANCELED,
    '部成': OrderStatus.DEALT,
    '已成': OrderStatus.DEALT,
    '废单': OrderStatus.FAILED
}


def parse_query_entrustments(account, data):
    def _parse(d):
        return {
            'account': account,
            'security': to_security(d['证券代码'], d['交易所代码']),
            'name': d['证券名称'],
            'buy_or_sell': d['买卖标志'] == '买入' and TradeCode.BUY or TradeCode.SELL,
            'hth': d['委托编号'],
            'quantity': float(d['委托数量']),
            'price': float(d['委托价格']),
            'avg_price': float(d['成交价格']),
            'state': mapping.get(d['状态说明'])
        }

    return [_parse(e) for e in data['data']]


def parse_query_balance(account, data):
    def _parse(d):
        cash = float(d['可用资金'])
        total_asset = float(d['总资产'])
        return {
            'account': account,
            'cash': cash,
            'total_asset': total_asset,
            'available_ratio': round(cash / total_asset, 4)
        }

    return [_parse(data['data'][0])]


def get_query_parse(category):
    if category == 0:
        return parse_query_balance
    elif category == 1:
        return parse_query_shares
    elif category == 2:
        return parse_query_entrustments
    else:
        return lambda account, data: data
